from tkinter import Tk, Label, Button, Text, END, filedialog
import struct

# Diccionario de notas, incluyendo silencio 'R'
notas_ay = {
    'R': (0, 0),
    'C2': (6, 175), 'C#2': (6, 78), 'D2': (5, 244), 'D#2': (5, 158), 'E2': (5, 78),
    'F2': (5, 1), 'F#2': (4, 186), 'G2': (4, 118), 'G#2': (4, 54), 'A2': (3, 249),
    'A#2': (3, 192), 'B2': (3, 138), 'C3': (3, 87), 'C#3': (3, 39), 'D3': (2, 250),
    'D#3': (2, 207), 'E3': (2, 167), 'F3': (2, 129), 'F#3': (2, 93), 'G3': (2, 59),
    'G#3': (2, 27), 'A3': (1, 253), 'A#3': (1, 224), 'B3': (1, 197), 'C4': (1, 172),
    'C#4': (1, 148), 'D4': (1, 125), 'D#4': (1, 104), 'E4': (1, 83), 'F4': (1, 64),
    'F#4': (1, 46), 'G4': (1, 29), 'G#4': (1, 13), 'A4': (0, 254), 'A#4': (0, 240),
    'B4': (0, 227), 'C5': (0, 214), 'C#5': (0, 202), 'D5': (0, 190), 'D#5': (0, 180),
    'E5': (0, 170), 'F5': (0, 160), 'F#5': (0, 151), 'G5': (0, 143), 'G#5': (0, 135),
    'A5': (0, 127), 'A#5': (0, 120), 'B5': (0, 113), 'C6': (0, 107), 'C#6': (0, 101),
    'D6': (0, 95), 'D#6': (0, 90), 'E6': (0, 85), 'F6': (0, 80), 'F#6': (0, 76),
    'G6': (0, 71), 'G#6': (0, 67), 'A6': (0, 64), 'A#6': (0, 60), 'B6': (0, 57)
}

# Interfaz
root = Tk()
root.title("Generador de Música AY")

Label(root, text="Canal A (nota/duración):").grid(row=0, column=0)
Label(root, text="Canal B (nota/duración):").grid(row=0, column=1)
Label(root, text="Canal C (nota/duración):").grid(row=0, column=2)

text_a = Text(root, height=30, width=20)
text_b = Text(root, height=30, width=20)
text_c = Text(root, height=30, width=20)

text_a.grid(row=1, column=0)
text_b.grid(row=1, column=1)
text_c.grid(row=1, column=2)

def generar_binario():
    notas_a = text_a.get("1.0", END).strip().splitlines()
    notas_b = text_b.get("1.0", END).strip().splitlines()
    notas_c = text_c.get("1.0", END).strip().splitlines()

    data_por_canal = []
    cantidades = []

    for canal, notas in enumerate([notas_a, notas_b, notas_c]):
        canal_data = bytearray()
        cantidad = 0
        for nota in notas:
            if nota.strip() == '':
                continue
            try:
                nombre, duracion = nota.strip().upper().split('/')
                duracion = int(duracion)
                byteh, bytel = notas_ay[nombre]
                canal_data.append(canal)
                canal_data += struct.pack('<B', byteh)
                canal_data += struct.pack('<B', bytel)
                canal_data += struct.pack('<H', duracion)
                cantidad += 1
            except Exception as e:
                print(f"Error con nota '{nota}': {e}")
        data_por_canal.append(canal_data)
        cantidades.append(cantidad)

    file_path = filedialog.asksaveasfilename(defaultextension=".bin",
                                             filetypes=[("Bin files", "*.bin")])
    if not file_path:
        return

    with open(file_path, "wb") as f:
        # Escribir los nuevos 6 bytes de encabezado
        f.write(struct.pack('<H', cantidades[0]))  # Canal A
        f.write(struct.pack('<H', cantidades[1]))  # Canal B
        f.write(struct.pack('<H', cantidades[2]))  # Canal C

        # Escribir las notas en orden: todas del canal A, luego B, luego C
        f.write(data_por_canal[0])
        f.write(data_por_canal[1])
        f.write(data_por_canal[2])

    print(f"Notas guardadas en '{file_path}' - A: {cantidades[0]}, B: {cantidades[1]}, C: {cantidades[2]}")

def guardar_txt():
    file_path = filedialog.asksaveasfilename(defaultextension=".txt",
                                             filetypes=[("Text files", "*.txt")])
    if not file_path:
        return
    with open(file_path, "w") as f:
        f.write("[CANAL A]\n")
        f.write(text_a.get("1.0", END))
        f.write("\n[CANAL B]\n")
        f.write(text_b.get("1.0", END))
        f.write("\n[CANAL C]\n")
        f.write(text_c.get("1.0", END))
    print(f"Notas guardadas en {file_path}")

def cargar_txt():
    file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
    if not file_path:
        return

    with open(file_path, "r") as f:
        contenido = f.read()

    secciones = {"A": "", "B": "", "C": ""}
    actual = None
    for linea in contenido.splitlines():
        linea = linea.strip()
        if linea.upper() == "[CANAL A]":
            actual = "A"
        elif linea.upper() == "[CANAL B]":
            actual = "B"
        elif linea.upper() == "[CANAL C]":
            actual = "C"
        elif actual and linea != "":
            secciones[actual] += linea + "\n"

    text_a.delete("1.0", END)
    text_b.delete("1.0", END)
    text_c.delete("1.0", END)
    text_a.insert(END, secciones["A"])
    text_b.insert(END, secciones["B"])
    text_c.insert(END, secciones["C"])
    print(f"Notas cargadas desde {file_path}")

# Botones
Button(root, text="Generar BIN", command=generar_binario).grid(row=2, column=1, pady=10)
Button(root, text="Guardar TXT", command=guardar_txt).grid(row=2, column=0)
Button(root, text="Cargar TXT", command=cargar_txt).grid(row=2, column=2)

root.mainloop()
